package cn.fan.service;

import cn.fan.constants.DataBaseConstants;
import cn.fan.feign.clients.FundClient;
import cn.fan.feign.pojo.FundData;
import cn.fan.feign.pojo.FundMain;
import cn.fan.mapper.UserInvestMapper;
import cn.fan.pojo.UserInvest;
import cn.fan.redis.UserInvestRedis;
import cn.fan.utils.R;
import cn.fan.utils.UserUtils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

@Service
public class UserInvestService {

    @Autowired
    private UserInvestMapper userInvestMapper;

    @Autowired
    private UserInvestRedis userInvestRedis;

    @Autowired
    private FundClient fundClient;

    public int add(UserInvest userInvest) {
        long sysUserId = UserUtils.getSysUserId();
        if (sysUserId == UserUtils.FAIL)
            return UserUtils.FAIL;

        FundMain fundMain = fundClient.selectByCode(userInvest.getFundcode());
        if (fundMain==null)
            return DataBaseConstants.NO_DATA;


        Map<String,Object> map=new HashMap<>();
        FundData fundData=new FundData();
        fundData.setCode(userInvest.getFundcode());
        String startDate=userInvest.getOperateDate();
        map.put("fundData",fundData);
        map.put("startDate",startDate);
        R r = fundClient.list(map);

        if( !"0".equals(r.get("code").toString()) || r.get("list")==null ){
            userInvest.setDwjz(0F);
        }else{
//            String listJson = JSON.toJSONString(r.get("list"));
//            List<FundData> fundDataList = JSONObject.parseObject(listJson,List.class);
//            if (fundDataList.size()>0)
//                userInvest.setDwjz(fundDataList.get(0).getNetworth());

            String listJson = JSON.toJSONString(r.get("list"));
            List fundDataList = JSONObject.parseObject(listJson,List.class);
            if (fundDataList.size()>0) {
                String str = JSON.toJSONString(fundDataList.get(0));
                FundData data0 = JSONObject.parseObject(str,FundData.class);
                userInvest.setDwjz(data0.getNetworth());
            }
        }

        setInvPartAttr(userInvest,fundMain);
        userInvest.setUserid(sysUserId);
        userInvest.setCreateDate(new Date());
        userInvest.setCreateBy(sysUserId);

        int i = userInvestMapper.insert(userInvest);
        userInvestRedis.putById(userInvest.getId(),userInvest);
        userInvestRedis.putList(userInvest.getUserid());
        return i;
    }

    public int delete(int id) {
        UserInvest invest = userInvestRedis.getById(id);
        if(invest==null)
            return DataBaseConstants.NO_DATA;

        int i = userInvestMapper.deleteById(id);
        userInvestRedis.delete(id);
        userInvestRedis.putList(invest.getUserid());
        return i;
    }

    public int edit(UserInvest userInvest){
        long sysUserId = UserUtils.getSysUserId();
        if (sysUserId == UserUtils.FAIL)
            return DataBaseConstants.NO_DATA;

        UserInvest invest = userInvestRedis.getById(userInvest.getId());
        if(invest==null)
            return DataBaseConstants.NO_DATA;

        invest.setOperateDate(userInvest.getOperateDate());
        invest.setShare(userInvest.getShare());
        invest.setDwjz(userInvest.getDwjz());
        invest.setCommission(userInvest.getCommission());
        invest.setSumMoney(userInvest.getSumMoney());
        invest.setUpdateBy(sysUserId);
        invest.setUpdateDate(new Date());

        int i = userInvestMapper.updateById(invest);
        userInvestRedis.putById(invest.getId(),invest);
        userInvestRedis.putList(invest.getUserid());

        return i;
    }

    public List<UserInvest> list(UserInvest userInvest) {
        long sysUserId = UserUtils.getSysUserId();
        if (sysUserId == UserUtils.FAIL)
            return new ArrayList<>();

        if(userInvest.getUserid()==null)
            userInvest.setUserid(sysUserId);

        LambdaQueryWrapper<UserInvest> queryWrapper = getUserInvestLambdaQueryWrapper(userInvest);

        List<UserInvest> list =userInvestMapper.selectList(queryWrapper);
        return list;
    }

    public IPage<UserInvest> page(UserInvest userInvest, long currentPage, long pageSize) {
        IPage<UserInvest> page = new Page<>(currentPage,pageSize);

        LambdaQueryWrapper<UserInvest> queryWrapper = getUserInvestLambdaQueryWrapper(userInvest);
        IPage<UserInvest> userIPage = userInvestMapper.selectPage(page, queryWrapper);
        return userIPage;
    }


    public UserInvest getById(int id) {
        return userInvestRedis.getById(id);
    }

    private LambdaQueryWrapper<UserInvest> getUserInvestLambdaQueryWrapper(UserInvest userInvest) {
        LambdaQueryWrapper<UserInvest> queryWrapper = new LambdaQueryWrapper<UserInvest>();
        queryWrapper.like(null!=userInvest.getFundcode(),
                UserInvest::getFundcode,
                userInvest.getFundcode());
        queryWrapper.eq(null!=userInvest.getUserid(),
                UserInvest::getUserid,
                userInvest.getUserid());
        queryWrapper.eq(null!=userInvest.getBuysellFlag(),
                UserInvest::getBuysellFlag,
                userInvest.getBuysellFlag());
        return queryWrapper;
    }

    private void setInvPartAttr(UserInvest userInvest,FundMain fundMain){
        if(userInvest.getDwjz()!=0F){
            if(userInvest.getShare()==null || userInvest.getShare()==0){
                System.out.println("userInvest:"+userInvest.toString());
                System.out.println("fundMain:"+fundMain.toString());
                float share=userInvest.getSumMoney() / (1+fundMain.getCommissionRate()/100) / userInvest.getDwjz();
                userInvest.setShare(share);
            }else if(userInvest.getSumMoney()==null || userInvest.getSumMoney()==0){
                float summoney=userInvest.getDwjz() * userInvest.getShare() * (1+fundMain.getCommissionRate()/100);
                userInvest.setSumMoney(summoney);
            }

            float com=userInvest.getSumMoney()-userInvest.getDwjz()*userInvest.getShare();
            userInvest.setCommission(com);
        }else{
            userInvest.setCommission(0F);
        }
    }

    public List<Map<String,Object>> overview() {
        long sysUserId = UserUtils.getSysUserId();
        if (sysUserId == UserUtils.FAIL)
            return new ArrayList<>();

        List<Map<String,Object>> result=new ArrayList<>();

        List<UserInvest> userInvests = userInvestMapper.selectByUserId(sysUserId);

        float indexSum_sumMoney=0;
        float indexSum_holdSum=0;
        float indexSum_profit=0;

        for(UserInvest invest:userInvests){
            Map<String,Object> map=new HashMap<>();
            float sumMoney=0;//投资总金额*
            float sellMoney=0;
            float holdSum=0;//持有总金额*
            float shareSum=0;//总投资份额*
            float shellShare=0;//卖出的份额
            float holdShare=0;//持有份额*
            float buyAVG=0;//买入均价*
            float holdAVG=0;//持有均价*
            float nowDwjz=0;//市值*(最新单位净值)
            float profit=0;//总亏盈*

            Map<String,Object> fundMap=new HashMap<>();
            FundData fundData=new FundData();
            fundData.setCode(invest.getFundcode());
            fundMap.put("fundData",fundData);

            R r= fundClient.list(fundMap);
            if( !"0".equals(r.get("code").toString()) || r.get("list")==null )
                continue;

            FundData newFundData=null;
            String listJson = JSON.toJSONString(r.get("list"));
            List fundDataList = JSONObject.parseObject(listJson,List.class);
            if (fundDataList.size()>0){
                String str = JSON.toJSONString(fundDataList.get(fundDataList.size()-1));
                newFundData = JSONObject.parseObject(str,FundData.class);
            }else
                continue;


            nowDwjz=newFundData.getNetworth();

            List<UserInvest> userInvestList=userInvestRedis.getList(sysUserId);
            if(userInvestList.size()==0)
                continue;

            for(UserInvest userInvest:userInvestList){
                if(userInvest.getBuysellFlag()==0){
                    sumMoney+=userInvest.getSumMoney();
                    shareSum+=userInvest.getShare();
                }else{
                    sellMoney+=userInvest.getSumMoney();
                    shellShare+=userInvest.getShare();
                }
            }

            holdShare=shareSum-shellShare;
            holdSum=holdShare*nowDwjz;
            profit=holdSum-sumMoney+sellMoney;
            buyAVG=sumMoney/shareSum;
            holdAVG=(sumMoney-sellMoney)/holdShare;

            map.put("fundcode",invest.getFundcode());
            map.put("sumMoney",sumMoney);
            map.put("holdSum",holdSum);
            map.put("shareSum",shareSum);
            map.put("holdShare",holdShare);
            map.put("buyAVG",buyAVG);
            map.put("holdAVG",holdAVG);
            map.put("nowDwjz",nowDwjz);
            map.put("profit",profit);
            result.add(map);

            indexSum_sumMoney+=sumMoney;
            indexSum_holdSum+=holdSum;
            indexSum_profit+=profit;
        }

        //汇总
        Map<String,Object> indexSum=new HashMap<>();

        indexSum.put("fundcode","");
        indexSum.put("sumMoney",indexSum_sumMoney);
        indexSum.put("holdSum",indexSum_holdSum);
        indexSum.put("shareSum","");
        indexSum.put("holdShare","");
        indexSum.put("buyAVG","");
        indexSum.put("holdAVG","");
        indexSum.put("nowDwjz","");
        indexSum.put("profit",indexSum_profit);
        result.add(indexSum);

        return result;
    }
}
